/**
 * 20220304:[require] to [import]...jordia
 */
import {Object3D,Raycaster,Vector2,Color} from 'three';
import Text from "../graphic/text";
import Texture from "./texture";
import Utils from "../general/utils";

/**
 * 位置标签
 */
export default class LocationLabel extends Object3D{
    constructor(values={}){
        super();
        this.values=values;
        this.init();
    }

    /**
     * 实体对象
     */
    get entity(){
        return this.body;
    }

    /**
     * 指定相机控制器并添加/移除事件
     * @param camCtr
     */
    set cameraCtr(camCtr){
        if(camCtr){
            if(this.camCtr!==null)return;
            this.camCtr=camCtr;
            this.camCtr.crossEvent.addEventListener('pointMove',this.onPointMove);
            this.camCtr.crossEvent.addEventListener('pointDown',this.onPointDown);
            this.camCtr.crossEvent.addEventListener('pointUp',this.onPointUp);
        }else{
            if(this.camCtr===null)return;
            this.camCtr.crossEvent.removeEventListener('pointMove',this.onPointMove);
            this.camCtr.crossEvent.removeEventListener('pointDown',this.onPointDown);
            this.camCtr.crossEvent.removeEventListener('pointUp',this.onPointUp);
            this.camCtr=null;
        }
    }

    /**
     * 设置点击回调函数
     * @param func
     */
    set onClick(func){
        this.clickCall=func;
    }

    /**
     * 销毁
     */
    dispose(){
        this.cameraCtr=null;
        this.body.dispose();
        this.caster=null;
        this.pointerStart=null;
        this.pointerVecStart=null;
        this.isPress=null;
        this.pointerEnd=null;
        this.threshold=null;
        this.clickFail=null;
        this.clickCall=null;
    }

    //..............................................................................

    init(){
        this.initVariable();
        this.initComponents();
        this.initEventBind();
    }

    /**
     * 初始化变量
     */
    initVariable(){
        this.body=null;
        this.camCtr=null;
        this.caster=new Raycaster();
        this.pointerStart=new Vector2();
        this.pointerVecStart=new Vector2();
        this.isPress=false;
        this.pointerEnd=new Vector2();
        this.threshold=10;
        this.clickFail=false;
        this.clickCall=null;
    }

    /**
     * 初始化组件
     */
    initComponents(){
        this.initEntity();
    }

    /**
     * 初始化标签实体
     */
    initEntity(){
        let size=(this.values.size||1)*256;
        let ca=Texture.locationMark(size,this.values.angle||30,0.9,{
            fill:this.values.color||'#ffffff',
            returnCanvas:true,
        });
        let tex=Texture.image(size,size,this.values.map.image||null,{
            width:size*0.7,
            height:size*0.7,
            dx:size*38/256,
            dy:size*32/256
        },ca);
        let t=new Text({
            map:tex,
            color:new Color(1,1,1)
        });
        t.material.alphaTest=this.values.alphaTest||0.5;
        t.center.set(this.values['centerX']||0.5,this.values['centerY']||0);
        this.body=t;
        this.add(this.body);
    }

    /**
     * 初始化事件句柄
     */
    initEventBind(){
        this.onPointDown=(e)=>{
            if(!this.visible)return;
            Utils.setCaster(this.camCtr.camera,this.camCtr.rect,e,this.caster,this.pointerStart,this.pointerVecStart);
            let intersection= this.caster.intersectObject(this.body,false);
            this.isPress=intersection.length>0;
            this.clickFail=false;
        };
        this.onPointMove=(e)=>{
            if(!this.visible)return;
            if(!this.isPress)return;
            if(this.clickFail)return;
            e.isMouse ? this.pointerEnd.set(e.clientX, e.clientY) : this.pointerEnd.set(e.touches[0].clientX, e.touches[0].clientY);
            this.clickFail=this.pointerStart.distanceToSquared(this.pointerEnd)>this.threshold;
        };
        this.onPointUp=(e)=> {
            if(!this.visible)return;
            if (!this.isPress)return;
            if(this.clickFail)return;
            if(this.clickCall)this.clickCall();
        };
    }
}